home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Celestin Apprentice 5
/
Apprentice-Release5.iso
/
Demos
/
Evatac Software
/
Preditor 3.0
/
Tools
/
Language Module Builder
/
Sources
/
CParse.c
< prev
next >
Wrap
Text File
|
1996-02-08
|
28KB
|
1,322 lines
/************************************************************
CParse.c
C Source to Preditor 3
Language Module Code for the "C" and "C++" language
© Copyright Evatac Software 1988-1996
All rights reserved
************************************************************/
#include "CParse.h"
#include <SetupA4.h>
#include <MixedMode.h>
#include <Ctype.h>
#ifndef THINKC
#include <A4Stuff.h>
#else
#define SetCurrentA4() 0; RememberA4()
#define SetA4(x) SetUpA4()
#endif
#ifdef powerc
ProcInfoType __procinfo = LanguageUPPInfo;
#endif
static languageGlobals globals;
static ExternalCallbackBlock *callbacks;
static languageToken *funcTokPtr;
/*
* * * * C LANGUAGE ELECTRIC HANDLER * * * * * *
*/
static long _languageConvertToTabs(
Char *text,
long length,
long hardTab
)
{
int tabs = length / hardTab;
int spaces = length % hardTab;
int newLen = tabs + spaces;
while (tabs-- > 0)
*(text++) = 9;
while (spaces-- > 0)
*(text++) = ' ';
return(newLen);
}
/*
* _languageHandleElectric
*
* We get called only when there is no selection, and one of the
* 3 electrics is pressed [;{}].
*/
static void _languageHandleElectric(
Char ch
)
{
long anchor, end, pos, length;
long i;
long lineNumber, leading;
short spacesPerTab, hardTab;
Char text[256], *ptr = text;
extGetSelection(callbacks, &anchor, &end);
lineNumber = extLineFromPosition(callbacks, anchor);
leading = extGetLeading(callbacks, lineNumber, &length,
&spacesPerTab, &hardTab);
pos = anchor;
anchor = extLineToPosition(callbacks, lineNumber);
/*
* Get the indentation of the current line
*/
if (ch == ';') {
/*
* Don't expand if we are in the middle a for statement. Doesn't
* catch if for is not first word in line, or the (;;) expression
* spans multiple lines
*/
length = 256 - 4;
extGetText(callbacks, anchor, end, text, &length);
text[length] = 0;
text[length+1] = 0;
while (*ptr == ' ' || *ptr == '\t')
ptr++;
ptr[3] = 0;
if (languageCStringCompare(ptr, (Char *) "for") == 0) {
/*
* Check to see if we are passed the ')'
*/
ptr += 4;
while (*ptr != 0) {
if (*ptr == ')')
break;
ptr++;
}
if (*ptr == 0) {
extInsert(callbacks, (Char *) ";", 1);
return;
}
}
/*
* Now create the text to insert
*/
text[0] = ';';
text[1] = '\r';
i = _languageConvertToTabs(text + 2, leading, hardTab);
extInsert(callbacks, text, i + 2);
}
else if (ch == '}') {
Int32 x;
Boolean sameLine;
/*
* See if we are on a blank line. If we are, put the '}' on it,
* otherwise, insert on a new line
*/
x = extLineEnd(callbacks, lineNumber);
sameLine = (x - anchor == length);
text[0] = '}';
text[1] = 0;
if ((x = extFindMatch(callbacks, text, end)) == -1) {
extInsert(callbacks, (Char *) "}", 1);
return;
}
lineNumber = extLineFromPosition(callbacks, x);
leading = extGetLeading(callbacks, lineNumber, &length,
&spacesPerTab, &hardTab);
/*
* Now create the text to insert
*/
if (sameLine) {
extSetSelection(callbacks, anchor, pos);
x = 0;
}
else {
text[0] = '\r';
x = 1;
}
i = _languageConvertToTabs(text + x, leading, hardTab);
text[i+x] = '}';
extInsert(callbacks, text, i + x + 1);
}
else if (ch == '{') {
/*
* Create the text to insert
*/
text[0] = '{';
text[1] = '\r';
i = _languageConvertToTabs(text + 2, leading + spacesPerTab, hardTab);
extInsert(callbacks, text, i + 2);
}
}
/*
* * * * C LANGUAGE INDENTING HANDLER * * * * * *
*/
/*
* _languageHandleIndent
*
* Indent the selected lines according to the buffer indentation settings
*/
static void _languageHandleIndent(
void *extData
)
{
long anchor, end, pos, length;
long lineStart;
long i, x, newPos = -1;
long lineNumber, endLineNumber, leading;
short spacesPerTab, hardTab;
Char text[256], ch;
extGetSelection(callbacks, &anchor, &end);
if (anchor > end) {
pos = anchor; anchor = end; end = pos; /* Swap */
}
lineNumber = extLineFromPosition(callbacks, anchor);
endLineNumber = extLineFromPosition(callbacks, end);
/*
* Indent each line in the selection
*/
while (lineNumber <= endLineNumber) {
if (lineNumber <= 1) {
lineNumber++;
continue;
}
leading = extGetLeading(callbacks, lineNumber, &length,
&spacesPerTab, &hardTab);
lineStart = extLineToPosition(callbacks, lineNumber);
/*
* Select the leading spaces/tabs
*/
extSetSelection(callbacks, lineStart, lineStart + length);
/*
* Scan back previous lines for a line that we can relate to
*/
x = 1;
for (;;) {
if (lineNumber - x < 1)
break;
leading = extGetLeading(callbacks, lineNumber - x, &length,
&spacesPerTab, &hardTab);
end = extLineEnd(callbacks, lineNumber - x);
pos = extLineToPosition(callbacks, lineNumber - x);
/* Skip Blank lines */
if (length == (end - pos)) {
x++;
continue;
}
i = pos + length;
/*
* Indent right if line contains a left bracket
*/
extScanContents(callbacks, i);
while (i++ < end && extNextScanCharacter(callbacks, &ch)) {
if (ch == '{') {
leading += spacesPerTab;
break;
}
}
extDoneScan(callbacks);
/*
* Indent the line
*/
i = _languageConvertToTabs(text, leading, hardTab);
extInsert(callbacks, text, i);
if (newPos == -1)
newPos = lineStart + i;
break;
}
lineNumber++;
}
if (newPos >= 0)
extSetSelection(callbacks, newPos, newPos);
}
/*
* * * * C LANGUAGE PARSER * * * * * *
*/
/*
* _languageBuildString
*
* Build up a literal string or literal contant "foo" or 'foo'
*/
static void _languageBuildString(
languageToken *token,
int c
)
{
Int32 index = 1, size = kTokenStringSize;
int origC = c;
token->string[1] = c;
token->type = (c == '\"' ? kSymbolStringLiteral : kSymbolCharConstant);
if (c == 'l' || c == 'L') {
c = languageGetChar(&globals, callbacks);
token->string[0] = c;
index = 2;
}
while ((c = languageGetChar(&globals, callbacks)) != -1) {
if (index < size)
token->string[++index] = c;
if (c == origC)
break;
else if (c == '\\') {
c = languageGetChar(&globals, callbacks);
if (c != -1) {
if (index < size)
token->string[++index] = c;
}
}
}
token->string[0] = index; /* So string can be used as C or Pascal string */
token->string[++index] = 0;
}
/*
* _languageBuildWhiteSpace
*
* Build up a directive (i.e. #define, etc)
*/
static void _languageBuildWhiteSpace(
languageToken *token,
int c
)
{
token->type = kSymbolWhiteSpace;
while ((c = languageGetChar(&globals, callbacks)) != -1) {
if (c != ' ' && c != '\t' && c != '\v' && c != '\n' &&
c != '\r' && c != '\f' && c != '\b') {
// if (!isspace(c)) {
languageUngetChar(&globals, c);
return;
}
}
}
/*
* _languageBuildComment
*
*/
static void _languageBuildComment(
languageToken *token,
int c
)
{
Boolean wasStar;
token->type = kSymbolComment;
globals.startLastComment = globals.position;
c = languageGetChar(&globals, callbacks);
if (c =='*') {
wasStar = false;
while ((c = languageGetChar(&globals, callbacks)) != -1) {
if (c == '*')
wasStar = true;
else if (c != '/' || !wasStar)
wasStar = false;
else
break;
}
}
else if (c == '/') {
while ((c = languageGetChar(&globals, callbacks)) != -1) {
if (c == 13)
break;
}
}
}
/*
* _languageBuildNumber
*
*/
static void _languageBuildNumber(
languageToken *token,
int c
)
{
token->type = kSymbolIntConstant;
if (c == '0') {
c = languageGetChar(&globals, callbacks);
if (c == 'x' || c == 'X') {
while ((c = languageGetChar(&globals, callbacks)) != -1) {
if ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'))
;
else
break;
}
}
else {
while (c != -1) {
if (c >= '0' && c <= '7')
;
else
break;
c = languageGetChar(&globals, callbacks);
}
}
}
else { /* decimal */
while ((c = languageGetChar(&globals, callbacks)) != -1) {
if (c >= '0' && c <= '9')
;
else
break;
}
if (c == '.') {
token->type = kSymbolFloatConstant;
while ((c = languageGetChar(&globals, callbacks)) != -1) {
if (c >= '0' && c <= '9')
;
else
break;
}
}
if (c == 'e' || c == 'E') {
token->type = kSymbolFloatConstant;
c = languageGetChar(&globals, callbacks);
if (c == '-' || c == '+')
c = languageGetChar(&globals, callbacks);
while (c != -1) {
if (c >= '0' && c <= '9')
;
else
break;
c = languageGetChar(&globals, callbacks);
}
}
}
while (c != -1) {
if (c == 'l' || c == 'L' || c == 'u' || c == 'U' ||
c == 'f' || c == 'F' || c == 'h' || c == 'H')
;
else
break;
c = languageGetChar(&globals, callbacks);
}
if (c != -1)
languageUngetChar(&globals, c);
}
/*
* _languageBuildInclude
*/
static void _languageBuildInclude(
languageToken *token,
int c
)
{
Int32 index = 0, size = kTokenStringSize;
int origC;
languageUngetChar(&globals, c);
_languageBuildWhiteSpace(token, c);
token->type = kSymbolInclude;
if ((c = languageGetChar(&globals, callbacks)) == '\"' || c == '<') {
origC = (c == '<' ? '>' : c);
while ((c = languageGetChar(&globals, callbacks)) != -1) {
if (c == origC)
break;
if (index < size)
token->string[++index] = c;
}
}
token->string[0] = index; /* So string can be used as C or Pascal string */
token->string[++index] = 0;
}
/*
* _languageBuildWord
*
*
*/
static void _languageBuildWord(
languageToken *token,
int c
)
{
Int32 index = 1, size = kTokenStringSize;
token->type = kSymbolIdentifier;
token->string[1] = c;
while ((c = languageGetChar(&globals, callbacks)) != -1) {
if (c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' || c == '_'
|| c >= '0' && c <= '9') {
if (index < size)
token->string[++index] = c;
}
else {
languageUngetChar(&globals, c);
break;
}
}
token->string[0] = index; /* So string can be used as C or Pascal string */
token->string[++index] = 0;
/*
* Since hashing into a large reserved word table takes time, the reserved
* word table is not loaded for "function" scanning. We do our own
* limited keyword check
*/
if (!languageHasTable(&globals)) {
Char *scan = token->string;
if (scan[1] == 't' && scan[2] == 'y' && scan[3] == 'p' && scan[4] == 'e' &&
scan[5] == 'd' && scan[6] == 'e' && scan[7] == 'f')
token->type = kSymbolReservedWord;
else if (scan[1] == '#' && scan[2] == 'p' && scan[3] == 'r' && scan[4] == 'a' &&
scan[5] == 'g' && scan[6] == 'm' && scan[7] == 'a')
token->type = kSymbolReservedWord;
else if (scan[1] == 'm' && scan[2] == 'a' && scan[3] == 'r' && scan[4] == 'k')
token->type = kSymbolReservedWord;
else if (scan[1] == 'o' && scan[2] == 'p')
token->type = kSymbolReservedWord;
return;
}
else if (languageTableLookup((&globals), token->string + 1))
token->type = kSymbolReservedWord;
else if (languageCustomTableLookup((&globals), token->string + 1))
token->type = kSymbolCustomWord;
}
/*
* _languageBuildDirective
*
* Build up a directive (i.e. #define, etc)
*/
static void _languageBuildDirective(
languageToken *token,
int c
)
{
int prevCh = c;
// _languageBuildWord(token, c);
token->type = kSymbolPreprocessorDirective;
while ((c = languageGetChar(&globals, callbacks)) != -1) {
if (c == 13 && prevCh != '\\')
break;
prevCh = c;
}
#if 0
Boolean isInsideComment;
int lastc;
token->type = kSymbolPreprocessorDirective;
lastc = 0;
while ((c = languageGetChar(&globals, callbacks)) != -1) {
if (c == '*' && lastc == '/')
isInsideComment = true;
if (isInsideComment && c == '/' && lastc == '*') {
isInsideComment = false;
lastc = ' ';
}
else
lastc = c;
if (!isInsideComment && c == 13)
break;
else if (c == '\\') {
c = languageGetChar(&globals, callbacks);
}
}
#endif
}
/*
* _languageConcatPStrings
*
* Concatenate two Pascal strings by attaching the second string on
* the end of the first string.
*/
static void _languageConcatPStrings(
Char *first,
Char *second
)
{
BlockMove(second + 1, first + first[0] + 1, (long) second[0]);
first[0] += second[0];
}
/*
* _languageGetNextToken
*/
static languageToken *_languageGetNextToken(void)
{
Int16 previousType;
languageToken *token = &globals.token;
int first, second;
previousType = token->type;
token->startLocation = globals.position;
token->majorType = -1;
if ((first = languageGetChar(&globals, callbacks)) == -1)
return(nil);
second = languagePeekChar(&globals, callbacks);
token->type = first;
token->string[1] = first;
token->string[2] = second;
if (previousType == kSymbolReservedWord &&
token->string[1] == '#' && token->string[2] == 'i' && token->string[3] == 'n') {
_languageBuildInclude(token, first);
first = 0;
}
switch(first) {
/* "strings" */
/* 'character constants' */
case '\"':
case '\'':
_languageBuildString(token, first);
break;
/* preprocessor directive */
case '#':
if (second != 'p') {
_languageBuildDirective(token, first);
globals.startLastComment = -1;
}
else
_languageBuildWord(token, first);
break;
/* white space */
case '\n': case '\r':
funcTokPtr->type = -1;
case ' ': case '\t': case '\v': case '\f': case '\b':
_languageBuildWhiteSpace(token, first);
break;
/* monographs */
case ';':
globals.startLastComment = -1;
case '(':
case ')':
case '[':
case ']':
case '{':
case '}':
case '\\':
case ',':
break;
/* / * can't nest comments * / also does / and /= */
case '/':
if (second == '*' || second == '/')
_languageBuildComment(token, first);
else if (second == '=') {
languageGetChar(&globals, callbacks);
token->type = kSymbolDivideAssign;
}
break;
/* *, *= */
case '*':
if (second == '=') {
languageGetChar(&globals, callbacks);
token->type = kSymbolMultiplyAssign;
}
break;
/* %, %= */
case '%':
if (second == '=') {
languageGetChar(&globals, callbacks);
token->type = kSymbolModAssign;
}
break;
/* !, != */
case '!':
if (second == '=') {
languageGetChar(&globals, callbacks);
token->type = kSymbolNotEqual;
}
break;
/* &, &=, && */
case '&':
if (second == '=') {
languageGetChar(&globals, callbacks);
token->type = kSymbolAndAssign;
}
else if (second == '&') {
languageGetChar(&globals, callbacks);
token->type = kSymbolAndAnd;
}
break;
/* |, ||, |= */
case '|':
if (second == '=') {
languageGetChar(&globals, callbacks);
token->type = kSymbolOrAssign;
}
else if (second == '|') {
languageGetChar(&globals, callbacks);
token->type = kSymbolOrOr;
}
break;
/* +, ++, += */
case '+':
if (second == '=') {
languageGetChar(&globals, callbacks);
token->type = kSymbolPlusAssign;
}
else if (second == '+') {
languageGetChar(&globals, callbacks);
token->type = kSymbolPlusPlus;
}
break;
/* -, --, -=, ->, ->* */
case '-':
if (second == '=') {
languageGetChar(&globals, callbacks);
token->type = kSymbolMinusAssign;
}
else if (second == '-') {
languageGetChar(&globals, callbacks);
token->type = kSymbolMinusMinus;
}
else if (second == '>') {
languageGetChar(&globals, callbacks);
second = languagePeekChar(&globals, callbacks);
if (second == '*') {
languageGetChar(&globals, callbacks);
token->type = kSymbolPointerStar;
}
else
token->type = kSymbolPointer;
}
break;
/* ., .*, .NUM */
case '.':
if (second == '*') {
languageGetChar(&globals, callbacks);
token->type = kSymbolDotStar;
}
else if (second >= '0' && second <= '9')
_languageBuildNumber(token, first);
else if (second == '.') {
languageGetChar(&globals, callbacks);
if (languagePeekChar(&globals, callbacks) == '.') {
languageGetChar(&globals, callbacks);
token->type = kSymbolEllipsis;
}
else {
languageUngetChar(&globals, second);
}
}
break;
/* =, == */
case '=':
if (second == '=') {
languageGetChar(&globals, callbacks);
token->type = kSymbolEqual;
}
break;
/* <, <<, <=, <<= */
case '<':
if (second == '=') {
languageGetChar(&globals, callbacks);
token->type = kSymbolLessOrEqual;
}
else if (second == '<') {
languageGetChar(&globals, callbacks);
second = languagePeekChar(&globals, callbacks);
if (second == '=') {
languageGetChar(&globals, callbacks);
token->type = kSymbolLeftShiftAssign;
}
else
token->type = kSymbolLeftShift;
}
break;
/* >, >=, >>, >>= */
case '>':
if (second == '=') {
languageGetChar(&globals, callbacks);
token->type = kSymbolGreaterOrEqual;
}
else if (second == '>') {
languageGetChar(&globals, callbacks);
second = languagePeekChar(&globals, callbacks);
if (second == '=') {
languageGetChar(&globals, callbacks);
token->type = kSymbolRightShiftAssign;
}
else
token->type = kSymbolRightShift;
}
break;
/* ^, ^= */
case '^':
if (second == '=') {
languageGetChar(&globals, callbacks);
token->type = kSymbolXOrAssign;
}
break;
/* :, :: */
case ':':
if (second == ':') {
languageGetChar(&globals, callbacks);
token->type = kSymbolScope;
}
break;
/* ?, ??=, ??/, ??', ??(, ??), ??! */
case '?':
if (second == '?') {
first = languageGetChar(&globals, callbacks);
second = languageGetChar(&globals, callbacks);
switch (second) {
case '=':
token->type = kSymbolTrigraphPound;
break;
case '/':
token->type = kSymbolTrigraphBackSlash;
break;
case '\'':
token->type = kSymbolTrigraphXOr;
break;
case '(':
token->type = kSymbolTrigraphLeftHard;
break;
case ')':
token->type = kSymbolTrigraphRightHard;
break;
case '!':
token->type = kSymbolTrigraphBar;
break;
default:
token->type = kSymbolTrigraphUnknown;
break;
}
}
break;
case 'l':
case 'L':
if (second == '\'' || second == '\"') {
_languageBuildString(token, first);
break;
}
/* fall through */
/* the rest */
default:
if (first >= '0' && first <= '9')
_languageBuildNumber(token, first);
else if (first >= 'a' && first <= 'z' || first >= 'A' && first <= 'Z' ||
first == '_' || first == '~')
_languageBuildWord(token, first);
/* Something weird, let the parser decide. */
break;
}
token->endLocation = globals.position;
return(token);
}
void languageMain(
ExternalCallbackBlock *extCallbacks,
WindowRef window,
long options,
void *extData
);
/*
* languageMain
*
* This is the main entrypoint to the CODE module of a language module.
* The following operations are defined:
*
* kLanguageParse Parse the source file, returning positions of all tokens
* in the file.
* kLanguageFunctions Parse the source file, returning the position of just the
* functions in the source file
* kLanguageIncludes Parse the source file, returning the #include files
* kLanguageTemplate Expand macro -- insert template
* kLanguageIndent
* kLanguageElectric Handle electric characters (i.e. }, {, ; )
*/
void main(
ExternalCallbackBlock *extCallbacks,
WindowRef window,
long options,
void *extData
)
{
int c;
languageToken *nextToken = nil, *token, tempToken;
languageToken saveToken, functionToken;
Int16 bracketLevel = 0, functionLevel = -1;
Int16 type, typedefLevel = -100;
Int32 typedefStart;
Boolean hadSemicolon;
long saved_a4;
saved_a4 = SetCurrentA4();
funcTokPtr = &functionToken;
languageInit(&globals, extCallbacks, options);
callbacks = extCallbacks;
if (options == kLanguageTemplate) {
languageDefaultHandler(&globals, callbacks, options, extData);
}
else if (options == kLanguageElectric) {
_languageHandleElectric((Char) extData);
}
else if (options == kLanguageIndent) {
_languageHandleIndent(extData);
}
else if (options <= kLanguageIncludes) {
/*
* Now parse the file, returning a series of valid return token types:
*
* kFunction
* kKeyword
* kComment
* kCustomKeyword
* kDisabledText
*/
functionToken.type = -1;
while (nextToken != nil || (token = _languageGetNextToken()) != nil) {
if (nextToken != nil) {
token = nextToken;
nextToken = nil;
}
type = token->type;
if (type == kSymbolReservedWord) {
if (options == kLanguageFunctions) {
if (token->string[1] == 't') { /* typedef */
typedefLevel = bracketLevel;
typedefStart = token->startLocation;
}
/* Handle #pragma mark <...> */
else if (token->string[1] == '#') { /* #pragma */
int index = 0;
while ((token = _languageGetNextToken()) != nil) {
if (token->type != kSymbolWhiteSpace)
break;
}
if (token != nil &&
token->type == kSymbolReservedWord &&
token->string[1] == 'm') {
token->startLocation = globals.position;
while ((c = languageGetChar(&globals, callbacks)) != -1 &&
c != 13) {
if (c == ' ' && index == 0) {
token->startLocation = globals.position;
continue;
}
if (index < kTokenStringSize)
token->string[++index] = c;
}
}
if (index > 0) {
token->endLocation = globals.position;
token->string[0] = index;
token->string[++index] = 0;
token->commentLocation = globals.startLastComment;
token->majorType = kFunction;
extTokenReturn(callbacks, token);
}
}
}
else {
token->majorType = kKeyword;
}
}
else if (type == kSymbolCustomWord) {
token->majorType = kCustomKeyword;
}
else if (type == kSymbolInclude && options == kLanguageIncludes) {
token->majorType = kFunction;
extTokenReturn(callbacks, token);
}
else if (type == kSymbolComment)
token->majorType = kComment;
else if (type == kSymbolPreprocessorDirective)
token->majorType = kDirective;
else if (type == kSymbolIdentifier && bracketLevel == 0 &&
functionToken.type == -1) {
saveToken = *token;
while ((token = _languageGetNextToken()) != nil) {
if (token->type == kSymbolScope) {
Int16 x, length = saveToken.string[0];
if (length < kTokenStringSize)
saveToken.string[++length] = ':';
if (length < kTokenStringSize)
saveToken.string[++length] = ':';
while ((token = _languageGetNextToken()) != nil) {
if (token->type == kSymbolWhiteSpace)
continue;
if (token->type == kSymbolReservedWord &&
token->string[1] == 'o' && token->string[2] == 'p') {
/*
* Get the operator
*/
tempToken = *token;
while ((token = _languageGetNextToken()) != nil) {
if (token->type == kSymbolWhiteSpace)
_languageConcatPStrings(tempToken.string, "\p ");
else if (token->type >= kSymbolLeftParen &&
token->type <= kSymbolLastCompoundSymbol) {
token->string[0] = (token->type >= kSymbolFirstCompoundSymbol ? 2 : 1);
_languageConcatPStrings(tempToken.string, token->string);
break;
}
else
break;
}
token = &tempToken;
}
else if (token->type != kSymbolIdentifier) {
nextToken = token;
token = nil;
break;
}
x = token->string[0];
if (length + x >= kTokenStringSize)
x = kTokenStringSize - length - 1;
BlockMove(token->string + 1,
saveToken.string + length + 1, x);
length += x;
break;
}
saveToken.endLocation = globals.position;
saveToken.string[0] = length;
saveToken.string[length+1] = 0;
continue;
}
if (token->type != kSymbolWhiteSpace)
break;
}
if (token == nil)
break;
if (token->type == kSymbolLeftParen) {
functionLevel = bracketLevel;
functionToken = saveToken;
functionToken.majorType = kFunction;
functionToken.commentLocation = globals.startLastComment;
hadSemicolon = false;
}
else {
nextToken = token;
continue;
}
}
else if (type == ';') {
if (typedefLevel == bracketLevel) {
saveToken.majorType = kFunction;
saveToken.commentLocation = typedefStart;
extTokenReturn(callbacks, &saveToken);
typedefLevel = -100;
}
else if (bracketLevel == functionLevel) {
hadSemicolon = true;
functionToken.type = -1;
}
}
else if (type == kSymbolLeftBrace)
bracketLevel++;
else if (type == kSymbolRightBrace) {
bracketLevel--;
if (bracketLevel >= 0 && bracketLevel == functionLevel) {
if (!hadSemicolon &&
(options == kLanguageFunctions || options == kLanguageParse)) {
extTokenReturn(callbacks, &functionToken);
}
functionLevel = -1;
functionToken.type = -1;
continue;
}
}
/*
* Only return a token if it's a interesting token, and
* if we are doing a full parse
*/
if (token->majorType >= 0 && options == kLanguageParse)
extTokenReturn(callbacks, token);
}
}
/*
* Clean up after ourselves
*/
languageDone(&globals, callbacks);
SetA4(saved_a4);
}